import socket
import os
import sys
import subprocess
import time
from datetime import datetime


PYTHON_PATH = '/usr/bin/python3' # 注意python路径是否正确
PORT = 8888 # 注意服务端口是否正确
# 检查是否有足够的参数
if len(sys.argv) > 1:
    # 获取第一个参数作为python脚本的路径
    PYTHON_PATH = sys.argv[1]
if len(sys.argv) > 2:
    # 获取第二个参数作为服务端口
    PORT = int(sys.argv[2])

# 获取当前脚本所在的目录
script_dir = os.path.dirname(os.path.abspath(__file__))
PYTHON_APP = os.path.join(script_dir, 'app.py')
LOG_FILE = os.path.join(script_dir, 'app.log')
LOCK_FILE = '/tmp/port_monitor.lock'
LOG_MAX_SIZE = 10 * 1024 * 1024  # 10 MB
LOG_BACKUP_COUNT = 5  # 保留5个备份日志文件

def check_port(port):
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(1)
            return s.connect_ex(('localhost', port)) == 0
    except Exception as e:
        print(f"端口检查错误: {e}")
        return True  # 假设端口被占用以防出错

def is_script_running():
    try:
        output = subprocess.check_output(['pgrep', '-f', PYTHON_APP])
        return bool(output.strip())
    except subprocess.CalledProcessError:
        return False

def write_log(message):
    # 确保日志文件存在
    if not os.path.exists(os.path.dirname(LOG_FILE)):
        os.makedirs(os.path.dirname(LOG_FILE), exist_ok=True)

    with open(LOG_FILE, 'a') as f:
        f.write(f"{datetime.now()}: {message}\n")

def log_rotate():
    # 检查日志文件是否存在
    if not os.path.exists(LOG_FILE):
        return

    # 检查日志文件大小是否超过限制
    if os.path.getsize(LOG_FILE) > LOG_MAX_SIZE:
        # 保留最多 LOG_BACKUP_COUNT 个备份日志文件
        for i in range(LOG_BACKUP_COUNT, 0, -1):
            src = f"{LOG_FILE}.{i}"
            dst = f"{LOG_FILE}.{i + 1}"
            if os.path.exists(src):
                os.rename(src, dst)

        # 将当前日志文件重命名为 .1
        os.rename(LOG_FILE, f"{LOG_FILE}.1")

def kill_running_script():
    try:
        output = subprocess.check_output(['pgrep', '-f', PYTHON_APP])
        pids = output.decode().strip().split('\n')
        for pid in pids:
            os.kill(int(pid), 9)
        write_log("已杀死所有运行中的脚本进程")
    except subprocess.CalledProcessError:
        write_log("没有找到运行中的脚本进程")

def main():
    # 防止并发执行
    if os.path.exists(LOCK_FILE):
        # 检查锁文件中的进程号是否仍在运行
        with open(LOCK_FILE, 'r') as f:
            pid = int(f.read().strip())
            if os.path.exists(f"/proc/{pid}"):
                print("另一个实例正在运行")
                return
    
    try:
        with open(LOCK_FILE, 'w') as f:
            f.write(str(os.getpid()))
        
        log_rotate()  # 调用日志轮询功能

        if not check_port(PORT):
            write_log("端口未被监听，检查脚本是否在运行")
            if is_script_running():
                write_log("脚本已在运行，但端口未被监听，杀死相关进程")
                kill_running_script()
            write_log("启动Python应用")
            subprocess.Popen(
                [PYTHON_PATH, PYTHON_APP],
                stdout=subprocess.DEVNULL,
                stderr=subprocess.STDOUT
            )
        else:
            write_log("端口已被监听，无需启动新应用")
    finally:
        if os.path.exists(LOCK_FILE):
            os.remove(LOCK_FILE)

if __name__ == "__main__":
    main()
